package dao.server;

import java.io.StringWriter;
import java.util.ArrayList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;

public class Project {
	private int id;
	private String name;
	private String time;
	private ArrayList<TestModule> listTestModule;
	private ArrayList<TestSuite> listTestSuite;
	private ArrayList<Function> listFunction;
	private ArrayList<TestData> listTestData;

	public Project() {
		this.name = "";
		this.time = "";
	}

	public Project(String name) {
		this.name = name;
	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getTime() {
		return time;
	}

	public void setTime(String time) {
		this.time = time;
	}

	public StringWriter objectToXml(DocumentBuilder docBuilder) {
		try {
			// document elements
			Document doc = docBuilder.newDocument();
			Element document = doc.createElement("document");
			doc.appendChild(document);

			// set attribute to document element
			Attr type = doc.createAttribute("type");
			type.setValue("PROJECT");
			document.setAttributeNode(type);

			Attr action = doc.createAttribute("action");
			action.setValue("");
			document.setAttributeNode(action);

			// head elements
			Element head = doc.createElement("head");
			document.appendChild(head);

			// id elements
			Element id = doc.createElement("id");
			id.appendChild(doc.createTextNode(String.valueOf(this.getId())));
			head.appendChild(id);

			// name elements
			Element name = doc.createElement("name");
			name.appendChild(doc.createTextNode(this.getName()));
			head.appendChild(name);

			// time elements
			Element time = doc.createElement("time");
			time.appendChild(doc.createTextNode(this.getTime()));
			head.appendChild(time);

			// body elements
			Element body = doc.createElement("body");
			document.appendChild(body);

			// modules elements
			Element modules = doc.createElement("modules");
			body.appendChild(modules);

			if (listTestModule != null && listTestModule.size() != 0) {
				for (TestModule tm : listTestModule) {
					// module elements
					Element module = doc.createElement("module");
					modules.appendChild(module);

					// set attribute to module element
					Attr idTM = doc.createAttribute("id");
					idTM.setValue(String.valueOf(tm.getId()));
					module.setAttributeNode(idTM);

					Attr nameTM = doc.createAttribute("name");
					nameTM.setValue(tm.getName());
					module.setAttributeNode(nameTM);

					if (tm.getListTestCase() != null
							&& tm.getListTestCase().size() != 0) {
						for (TestCase tc : tm.getListTestCase()) {
							// test case elements
							Element testcase = doc.createElement("testcase");
							testcase.appendChild(doc.createTextNode(tc
									.getName()));
							module.appendChild(testcase);

							// set attribute to test case element
							Attr idTC = doc.createAttribute("id");
							idTC.setValue(String.valueOf(tc.getId()));
							testcase.setAttributeNode(idTC);
							
							// set attribute to test case element
							Attr idTS = doc.createAttribute("id_testscript");
							idTS.setValue(String.valueOf(tc.getTS().getId()));
							testcase.setAttributeNode(idTS);
						}
					}
				}
			}
			// functions elements
			Element functions = doc.createElement("functions");
			body.appendChild(functions);
			if (listFunction != null && listFunction.size() != 0) {
				for (Function f : listFunction) {
					// function elements
					Element function = doc.createElement("function");
					function.appendChild(doc.createTextNode(f.getName()));
					functions.appendChild(function);

					// set attribute to function element
					Attr idF = doc.createAttribute("id");
					idF.setValue(String.valueOf(f.getId()));
					function.setAttributeNode(idF);
				}
			}

			// suites elements
			Element suites = doc.createElement("suites");
			body.appendChild(suites);

			if (listTestSuite != null && listTestSuite.size() != 0) {
				for (TestSuite ts : listTestSuite) {
					// suite elements
					Element suite = doc.createElement("suite");
					suites.appendChild(suite);

					// set attribute to suite element
					Attr idTS = doc.createAttribute("id");
					idTS.setValue(String.valueOf(ts.getId()));
					suite.setAttributeNode(idTS);

					Attr nameTS = doc.createAttribute("name");
					nameTS.setValue(ts.getName());
					suite.setAttributeNode(nameTS);

					if (ts.getListTestCase() != null
							&& ts.getListTestCase().size() != 0) {
						for (TestCase tc : ts.getListTestCase()) {
							// test case elements
							Element testcase = doc.createElement("testcase");
							testcase.appendChild(doc.createTextNode(tc
									.getName()));
							suite.appendChild(testcase);

							// set attribute to test case element
							Attr idTC = doc.createAttribute("id");
							idTC.setValue(String.valueOf(tc.getId()));
							testcase.setAttributeNode(idTC);
						}
					}
				}
			}
			// test data elements
			Element testdatas = doc.createElement("testdatas");
			body.appendChild(testdatas);
			if (listTestData != null && listTestData.size() != 0) {
				for (TestData td : listTestData) {
					// test data elements
					Element testdata = doc.createElement("testdata");
					testdata.appendChild(doc.createTextNode(td.getName()));
					testdatas.appendChild(testdata);

					// set attribute to test data element
					Attr idTD = doc.createAttribute("id");
					idTD.setValue(String.valueOf(td.getId()));
					testdata.setAttributeNode(idTD);
				}
			}
			// test results elements
			Element testresults = doc.createElement("testresults");
			body.appendChild(testresults);

			if (listTestSuite != null && listTestSuite.size() != 0) {
				for (TestSuite ts : listTestSuite) {					
					if (ts.getListTestResult() != null
							&& ts.getListTestResult().size() != 0) {
						for (TestResult tr : ts.getListTestResult()) {
							// test result elements
							Element testresult = doc.createElement("testresult");
							testresult.appendChild(doc.createTextNode(tr.getName()));
							testresults.appendChild(testresult);

							// set attribute to test suite element
							Attr idTR = doc.createAttribute("id");
							idTR.setValue(String.valueOf(tr.getId()));
							testresult.setAttributeNode(idTR);
						}
					}
				}
			}
			// write the content into xml file
			TransformerFactory transformerFactory = TransformerFactory
					.newInstance();
			Transformer transformer = transformerFactory.newTransformer();
			DOMSource source = new DOMSource(doc);
			StringWriter sw = new StringWriter();
			StreamResult result = new StreamResult(sw);
			transformer.transform(source, result);
			return sw;
		} catch (Exception e) {
			//e.printStackTrace();
			return null;
		}
	}

	public void xmlToObject(Document doc) {
		try {
			NodeList nodeList = doc.getElementsByTagName("head");
			Element element = (Element) nodeList.item(0);
			try {
				this.setId(Integer.parseInt(element.getElementsByTagName("id")
						.item(0).getTextContent()));
			} catch (NumberFormatException nfe) {
				this.setId(0);
			}
			this.setName(element.getElementsByTagName("name").item(0)
					.getTextContent());
			this.setTime(element.getElementsByTagName("time").item(0)
					.getTextContent());
		} catch (Exception e) {
			//e.printStackTrace();
		}
	}

	public void getListTestModule(DAO dao) {
		listTestModule = dao.getAllTestModule(this.getId());
		if (listTestModule != null && listTestModule.size() != 0) {
			for (TestModule tm : listTestModule) {
				tm.getModule(dao);
			}
		}
	}

	public void getListTestSuite(DAO dao) {
		listTestSuite = dao.getAllTestSuite(this.getId());
		if (listTestSuite != null && listTestSuite.size() != 0) {
			for (TestSuite ts : listTestSuite) {
				ts.getTestSuite(dao);
			}
		}
	}

	public void getListFunction(DAO dao) {
		listFunction = dao.getAllFunctionInProject(this.getId());
	}

	public void getListTestData(DAO dao) {
		listTestData = dao.getAllTestData(this.getId());
	}

	public String addProject(DAO dao) {
		if (dao != null)
			if (dao.addProject(this)){
				dao.addTestModule(new TestModule(this.getId(),"Default Module","","Default module"));
				dao.addTestSuite(new TestSuite(this.getId(),"Default Test Suite","","Default test suite"));
				return String.valueOf(id);
			}
			else
				return "Project " + this.getName() + " already exist";
		return "Create project " + this.getName()
				+ " unsuccess, please try again!";
	}

	public String updateProject(DAO dao) {
		if (dao != null){
			Project p = dao.getProject(this.getId());
			if(p == null || p.getId() == 0)
				return "Can't find the project";
			if (dao.updateProject(this))
				return "Update project success";
			else
				return "Project " + this.getName() + " already exist";
		}
		return "Update project unsuccess, please try again!";
	}

	public String deleteProject(DAO dao) {
		if (dao != null){
			Project p = dao.getProject(this.getId());
			if(p == null || p.getId() == 0)
				return "Can't find the project";
			if (dao.deleteProject(p))				
				return "Remove project " + this.getName() + " success";
		}
		return "Remove project " + this.getName()
				+ " unsuccess, please try again!";
	}

	public void getProject(DAO dao) {
		getListTestModule(dao);
		getListTestSuite(dao);
		getListFunction(dao);
		getListTestData(dao);
	}
}
